#!/usr/bin/env python

import os
import sys

def save(fn, lines):
	try:
		f = open(fn, "wt")
		for line in lines:
			f.write(line+"\n\n")	
		f.close()
	except:
		print "fail to write: ", fn

class UnsupportedFileTypeException:
	def __init__(self, value):
		self.value = value
	def __str__(self):
		return repr(self.value)

class DocumentLoader:
	def __init__(self, fn):
		self.fn = fn
		self.fn_base = fn[:-3]
		self.paragraphs = None
		self.sentences = None

	def load(self):
		self._extract_paragraphs()
		self._extract_sentences()

	def _save(self, fn, lines):
		save(fn, lines)

	def _extract_sentences(self):
		self.sentences=[]

		sentences = []
		for p in self.paragraphs:
			p = p.replace(':', '.')
			sentences += filter(lambda x: len(x) > 0, map(lambda x: x.strip(), p.split(".")))

		#copy sentences to self.sentences with fixing "fi" 
		for s in sentences:
			s = s.replace("\xef\xac\x81", "fi")
			s = s.replace("\xef\xac\x82", "fl")
			self.sentences.append(s)
	
		#self._save(self.fn_base+"sen", self.sentences)	

class PDFDocumentLoader(DocumentLoader):
	def _extract_paragraphs(self):
		os.system("pdftotext %s" % self.fn)
		txtfn = self.fn_base+"txt"
		txtloader = TXTDocumentLoader(txtfn)
		txtloader._extract_paragraphs()
		os.system("rm %s" % txtfn)

		self.paragraphs = txtloader.paragraphs
		

# return True if the line s is not ""
def NullFilter(s):
	return len(s) > 0

def CapitalFilter(s):
	return s[0].isupper()

# return True if the line is not a Title
def TitleFilter(s):
	words = s.split()
	cap = map(lambda x: x[0].isupper(), words)
	if len(words) == 1:
		return not words[0][0].isupper()
	else:
		return len(filter(lambda x: x, cap)) < len(cap) / 2

def isInSentence(s):
	return TitleFilter(s)

def SectionNumberFilter(s):
	return True

# return true if the string is the first line of a paragraph
def PreFilter(s):
	filters = [NullFilter, CapitalFilter, TitleFilter]
	for f in filters:
		if not f(s): return False
	
	return True

def CancelFilter(s):
	return len(s) == 0

def ColonFilter(s):
	return s.endswith(":") or s.endswith(".")

# return true if the string is the last line of a paragraph
def PostFilter(s):
	filters = [ColonFilter]
	for f in filters:
		if f(s) == False: return False

	return True
	
class TXTDocumentLoader(DocumentLoader):
	def _extract_paragraphs(self):
		self.paragraphs = []
		self.cancelled = []
		MODE_NONE = 0
		MODE_LASTSENTENCE = 1
		MODE_CANCELLED = 2
		mode = MODE_NONE
		is_continue = False
		
		try:
			f = open(self.fn, "rt")
			paragraph = ""
			for line in f:
				is_continue = False
				s = line.replace('\r\n', "")
				s = s.replace('\r', "").replace('\n', "")
				s = s.strip()
				if s.endswith('-'):
					s = s[:-1]
					is_continue = True

				if mode == MODE_CANCELLED and isInSentence(s):
					paragraph = self.cancelled.pop()
					mode = MODE_NONE

				if not paragraph and PreFilter(s):
					if mode == MODE_LASTSENTENCE:
						paragraph = self.paragraphs.pop()
						paragraph += " " + s
					else:
						paragraph = s
				elif paragraph:
					if is_continue:
						paragraph += s
						is_continue = False
					else:
						paragraph += " " + s

				mode = MODE_NONE

				if paragraph:
					if CancelFilter(s):
						self.cancelled.append(paragraph)
						paragraph = ""
						mode = MODE_CANCELLED
					elif PostFilter(s):
						self.paragraphs.append(paragraph)
						paragraph = ""
						mode = MODE_LASTSENTENCE

			f.close()
		except Exception as e:
			print e
			print "Fail to open %s" % self.fn

		#self._save(self.fn_base+"para", self.paragraphs)
		#self._save(self.fn_base+"can", self.cancelled)

class Document:
	def __init__(self, fn=None):
		if (fn):
			self.fn = fn
			self.fn_base = fn[:-3]
			self._load()

	def _load(self):
		fn = self.fn
		if (fn.endswith(".pdf")):
			self.loader = PDFDocumentLoader(fn)
		elif (fn.endswith(".txt")):
			self.loader = TXTDocumentLoader(fn)
		else:
			raise UnsupportedFileTypeException(fn.split(".")[-1])
			
		self.loader.load()
		self.sentences = self.loader.sentences

if __name__=="__main__":
	fn = sys.argv[1]
	doc = Document(fn)

